package com.gshg.log.cleanlog.service;


import com.alibaba.fastjson.JSONObject;
import com.gshg.log.cleanlog.bo.LogCleanPolicyBO;
import com.gshg.log.cleanlog.utils.DateUtil;
import com.gshg.log.cleanlog.utils.FileUtil;
import com.gshg.log.cleanlog.utils.ZIPUtil;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.*;

import static com.gshg.log.cleanlog.utils.FileUtil.getFiles;


@Slf4j
@Service
public class LogCleanService {

    @Value("${quartz.log-clean.policy-file}")
    private String policyFile;


    public void cleanLogDeal(){
        //策略文件处理
        Map<String, List<LogCleanPolicyBO>> policyMap = getLogCleanPolicy(policyFile);
        if(policyMap.isEmpty()){
            return;
        }
        Set<String> keySet = policyMap.keySet();
        for(String key : keySet){
            switch (key){
                case "del_file":
                    List<LogCleanPolicyBO> listDel = policyMap.get(key);
                    if(null != listDel){
                       for(LogCleanPolicyBO bo : listDel){
                           deleteLogFile(bo);
                       }
                    }
                    break;
                case "clean_content":
                    List<LogCleanPolicyBO> listCommand = policyMap.get(key);
                    if(null != listCommand){
                        for(LogCleanPolicyBO bo : listCommand){
                            processCommand(bo.getCommand());
                        }
                    }
                    break;
                case "zip_file":
                    List<LogCleanPolicyBO> listZip = policyMap.get(key);
                    if(null != listZip){
                        for(LogCleanPolicyBO bo : listZip){
                            zipLogFile(bo);
                        }
                    }
                    break;
                default:
                     //不做任何处理
            }

        }
    }


    private Map<String, List<LogCleanPolicyBO>> getLogCleanPolicy(String policyFilePath){
        Map<String, List<LogCleanPolicyBO>> result = new HashMap<>();
        File policyFile = new File(policyFilePath);
        try {
            List<String> list =  FileUtils.readLines(policyFile, "UTF-8");
            if(null != list && !list.isEmpty()){
                for(String str : list){
                    if(StringUtils.isNotEmpty(str) && !str.startsWith("#")){
                        int i = str.indexOf("=");
                        String key = str.substring(0, i);
                        String jsonStr = str.substring(i+1);
                        if(result.containsKey(key)){
                            result.get(key).add(JSONObject.parseObject(jsonStr, LogCleanPolicyBO.class));
                        }else{
                            List<LogCleanPolicyBO> bos = new ArrayList<>();
                            bos.add(JSONObject.parseObject(jsonStr, LogCleanPolicyBO.class));
                            result.put(key, bos);
                        }
                    }
                }
            }
        } catch (IOException e) {
            log.error(e.getLocalizedMessage(), e);
        }

        return result;
    }

    private void processCommand(String command){
        Process process = null;
        try {
            String commandFix = command.replaceAll(" ", "");
            if(commandFix.contains("rm-rf")){
                return;
            }
            process = Runtime.getRuntime().exec(command);
            process.waitFor(); //用来等待process调用的命令执行结束，如果该命令可以和程序并行跑，则不需要等待
            int exitValue = process.exitValue(); //获取操作系统命令的执行结果，Linux中0代表成功，其他代表失败
            if (exitValue != 0) {
                log.info(MessageFormat.format("command execute failed：command={0}；exitValue={1}", command, exitValue));
            }
        } catch (IOException e) {
            log.error(e.getLocalizedMessage(), e);
        } catch (InterruptedException e) {
            log.error(e.getLocalizedMessage(), e);
        }
    }

    private void deleteLogFile(LogCleanPolicyBO bo){
        try {
            if(!"del_file".equalsIgnoreCase(bo.getCleanType())){
                log.error(MessageFormat.format("日志清理类型错误：{0}", bo.toJSONString()));
                return;
            }


            //获取传入路径下的全部文件
            File fileDir = new File(bo.getFilePath());
            if (!fileDir.exists()) {
                log.error(MessageFormat.format("文件不存在：{0}", bo.toJSONString()));
                return ;
            }

            if (!fileDir.isDirectory()) {
                log.error(MessageFormat.format("文件路径错误：{0}", bo.toJSONString()));
                return ;
            }

            File[] fileArray = getFiles(fileDir, bo.getLogFilePrefix(), bo.getLogNameTemplate(), bo.getRetainDay());

            if (null == fileArray || fileArray.length == 0) {
                log.error("获取不到日志文件[" + bo.toJSONString() + "]");
                return ;
            }
            for (int i = 0; i < fileArray.length; i++) {
                fileArray[i].delete();
            }
        }catch (Exception e){
            log.error(e.getLocalizedMessage(), e);
        }
    }


    private void zipLogFile(LogCleanPolicyBO bo){
        try {
            if(!"zip_file".equalsIgnoreCase(bo.getCleanType())){
                log.error(MessageFormat.format("日志清理类型错误：{0}", bo.toJSONString()));
                return;
            }


            //获取传入路径下的全部文件
            File fileDir = new File(bo.getFilePath());
            if (!fileDir.exists()) {
                log.error(MessageFormat.format("文件不存在：{0}", bo.toJSONString()));
                return ;
            }

            if (!fileDir.isDirectory()) {
                log.error(MessageFormat.format("文件路径错误：{0}", bo.toJSONString()));
                return ;
            }

            File[] fileArray = FileUtil.getFiles(fileDir, bo.getLogFilePrefix(), bo.getLogNameTemplate(), bo.getRetainDay());

            if (null == fileArray || fileArray.length == 0) {
                log.error("获取不到日志文件[" + bo.toJSONString() + "]");
                return ;
            }

            String zipFilePath = bo.getZipFilePath();
            File zipDir = new File(zipFilePath);
            if(!zipDir.exists()){
                zipDir.mkdir();
            }
            if(!zipFilePath.endsWith(File.separator)){
                zipFilePath = zipFilePath + File.separator;
            }
            String zipFileNamePre = "";
            if(StringUtils.isNotEmpty(bo.getLogFilePrefix())){
                zipFileNamePre = bo.getLogFilePrefix()+"_";
            }
            Date fileNameDate = DateUtil.getDateBeforeSomeDate(new Date(), -bo.getRetainDay());

            String zipLogFileName = zipFileNamePre + DateUtil.dateFormatString("yyyy-MM-dd", fileNameDate)+".zip";
            File zipFile = new File(zipFilePath+zipLogFileName);
            int zi=0;
            while(zipFile.exists()){
                zipLogFileName =  zipFileNamePre + DateUtil.dateFormatString("yyyy-MM-dd", fileNameDate)+ "_"+ zi +".zip";
                zipFile = new File(zipFilePath+zipLogFileName);
                zi++;
            }
            ZIPUtil.zipFiles(fileArray, zipFile);
            for (int i = 0; i < fileArray.length; i++) {
                fileArray[i].delete();
            }
        }catch (Exception e){
            log.error(e.getLocalizedMessage(), e);
        }
    }
}
